Odin Structs

Table of Contents

1. Struct Definition

The basic grammar for structs is similar to C.

  Rectangle :: struct {
    x: f32,
    y: f32,
    width: f32,
    height: f32,
  }

Then we can use := to initialize instances.

  rect := Rectangle {
    width = 20,
    height = 10,
  }

Unmentioned fields will be automatically initialized to zero value.

2. Structs within Structs

Basically, since structs are types, so we can define fields of other structs within a struct.

  Person_Stats :: struct {
    health: int,
    age: int,
  }

  Person :: struct {
    stats: Person_Stats,
    name: string,
  }

We can then initialize Person instances in a nested way, as well as accessing Person fields nestedly.

  p := Person {
    stats = {
      health = 7,
    },
    name = "Bob",
  }

  p.name = "Bobinski"
  p.stats.age = 36

2.1. using on Struct Fields

It’s sometime too redundant to type p.stats.age. By using keyword, we can make age field directly available on p.

  Person :: struct {
    using stats: Person_Stats,
    name: string,
  }

Not only we can access it directly, we can also initialize it directly.

  p := Person {
    health = 7,
    name = "Bob",
  }

2.2. using Acts like Inheritance

The using keyword can play the role of inheritance to some extend. In this example, although p is of type Person, but since Person is using type Entity, calling printposition with p that requires an Entity argument still compiles.

Entity :: struct {
    id: int,
    position: [2]int,
}

Person :: struct {
    using entity: Entity,
    health: int,
}

print_position :: proc(e: Entity) {
    fmt.println(e.position)
}

main :: proc() {
    p := Person {
        id = 1,
        position = {6, 7},
        health = 20,
    }

    print_position(p)
}

3. Using Structs as Interfaces

Although we cannot define methods on structs, we can do something similar to storing function pointers in C to make a struct an interface.

  Interface :: struct {
      required_name: int,
      is_valid: proc(Interface, string) -> bool,
  }

  my_proc :: proc(i: Interface, name: string) -> bool {
      return i.required_name == name
  }

  my_interface := Interface {
      required_name = "Sf",
      is_valid = my_proc,
  }

Date: 2026-07-17 Fri